﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using nyxwin.Main.Base.ViewModels;
using nyxwin.Common.Settings;
using nyxwin.Data.Mail;
using System.Collections.Generic;
using System.Linq;
using nyxwin.Main.ViewModel.SubModels;
using Microsoft.Phone.Controls;
using nyxwin.Common.Silverlight.Commands;

namespace nyxwin.Main.ViewModel.Main
{
    public class MailViewModel : PivotItemViewModel
    {
        private static readonly Guid GETTINGMAILS_ID = Guid.NewGuid();

        private AppBarButton _searchButton;
        private AppBarButton _refreshButton;
        private MailQuery _lastSearchQuery;
        private bool _working;
        private bool _firstLoad;

        public MailViewModel()
        {
            Mails = new List<MailModel>();
            _working = false;
            _firstLoad = true;

            _newMessageButton = new AppBarButton(new Uri("/Icons/add.png", UriKind.Relative), () =>
            {
                Navigate(new Uri("/View/SubViews/NewMail.xaml", UriKind.Relative));
            })
            {
                IsEnabled = true
            };
            _searchButton = new AppBarButton(new Uri("/Icons/search.png", UriKind.Relative), () =>
            {
                if (QueryVisible)
                {
                    if (!string.IsNullOrEmpty(FilterByNick) || !string.IsNullOrEmpty(FilterByContent))
                    {
                        Refresh();
                    }
                    else
                    {
                        ResetQuery();
                    }
                }
                else
                {
                    QueryVisible = true;
                }
            })
            {
                IsEnabled = true
            };

            _refreshButton = new AppBarButton(new Uri("/Icons/refresh.png", UriKind.Relative), () => Refresh())
            {
                IsEnabled = true
            };

            FilterCommand = new Command(x =>
            {
                if (Working)
                    return;

                Working = true;
                SetIsInDeterminate(GETTINGMAILS_ID, Localization.GetString("GettingMails"));
                var mailMgr = new MailManager(ApplicationSettings.Instance.AuthorizationNick, ApplicationSettings.Instance.AuthorizationToken);
                mailMgr.GetMailsCompleted += new EventHandler<GetMailsEventArgs>(mailMgr_GetMailsCompleted);
                mailMgr.ErrorOccurred += new EventHandler<Data.Base.ErrorOccurredEventArgs>(mailMgr_ErrorOccurred);

                var query = new MailQuery();
                query.FilterUser = FilterByNick;
                query.FilterContents = FilterByContent;

                _lastSearchQuery = query;

                mailMgr.GetMails(query);
            }, x => NotWorking);

            FilterByNickCommand = new Command(x =>
            {
                if (x is string)
                {
                    FilterByNick = (string)x;
                    FilterCommand.Execute(null);
                }
            }, x => NotWorking);

            ActualizeAppBarTitles();

            _lastSearchQuery = null;

            MoreCommand = new Command(x =>
            {
                if (Working)
                    return;

                Working = true;
                SetIsInDeterminate(GETTINGMAILS_ID, Localization.GetString("GettingMails"));
                var mailMgr = new MailManager(ApplicationSettings.Instance.AuthorizationNick, ApplicationSettings.Instance.AuthorizationToken);
                mailMgr.GetMailsCompleted += new EventHandler<GetMailsEventArgs>(mailMgr_GetMailsCompleted_Append);
                mailMgr.ErrorOccurred += new EventHandler<Data.Base.ErrorOccurredEventArgs>(mailMgr_ErrorOccurred);

                var query = new MailQuery();

                if (_lastSearchQuery != null)
                {
                    query.FilterUser = _lastSearchQuery.FilterUser;
                    query.FilterContents = _lastSearchQuery.FilterContents;
                }

                if (this.Mails.Count > 0)
                {
                    query.LastId = this.Mails.Min(y => y.Id);
                }

                mailMgr.GetMails(query);
            }, x => NotWorking);
        }

        private void ActualizeAppBarTitles()
        {
            _newMessageButton.Title = Localization.GetString("NewMessageButtonTitle");
            _searchButton.Title = Localization.GetString("SearchButtonTitle");
            _refreshButton.Title = Localization.GetString("RefreshButtonTitle");
        }

        protected override void OnLocalizationChanged()
        {
            base.OnLocalizationChanged();
            ActualizeAppBarTitles();
            RaisePropertyChanged(() => Title);
        }

        public override string Title
        {
            get
            {
                return Localization.GetString("MailTitle");
            }
        }

        private void Refresh()
        {
            if (Working)
                return;

            ResetQuery();
            Working = true;
            SetIsInDeterminate(GETTINGMAILS_ID, Localization.GetString("GettingMails"));
            var mailMgr = new MailManager(ApplicationSettings.Instance.AuthorizationNick, ApplicationSettings.Instance.AuthorizationToken);
            mailMgr.GetMailsCompleted += new EventHandler<GetMailsEventArgs>(mailMgr_GetMailsCompleted);
            mailMgr.ErrorOccurred += new EventHandler<Data.Base.ErrorOccurredEventArgs>(mailMgr_ErrorOccurred);

            if (_firstLoad)
            {
                Mails = (mailMgr.GetMails(MailQuery.Default) ?? new List<Mail>()).Select(x => new MailModel(x, FilterByNickCommand)).ToList();
                _firstLoad = false;
            }
            else
            {
                mailMgr.GetMails(MailQuery.Default);
            }
        }

        void mailMgr_ErrorOccurred(object sender, Data.Base.ErrorOccurredEventArgs e)
        {
            Dispatcher.BeginInvoke(() =>
            {
                UnSetInDeterminate(GETTINGMAILS_ID);
                Working = false;
                RaiseError(e.ErrorMessage);
            });
        }

        void mailMgr_GetMailsCompleted(object sender, GetMailsEventArgs evArgs)
        {
            Dispatcher.BeginInvoke(() =>
            {
                if (!evArgs.Error)
                {
                    if (Mails != null)
                        foreach (var mail in Mails)
                        {
                            mail.Unload();
                        }

                    Mails = evArgs.MailList.Select(x => new MailModel(x, FilterByNickCommand)).ToList();
                }
                else
                {
                    RaiseError(evArgs.ErrorMessage);
                }

                UnSetInDeterminate(GETTINGMAILS_ID);
                Working = false;
            });
        }

        void mailMgr_GetMailsCompleted_Append(object sender, GetMailsEventArgs evArgs)
        {
            Dispatcher.BeginInvoke(() =>
            {
                if (!evArgs.Error)
                {
                    var list = new List<MailModel>(Mails);

                    foreach (var newMail in evArgs.MailList)
                    {
                        if (!list.Select(x => x.Id).Contains(newMail.Id))
                        {
                            list.Add(new MailModel(newMail, FilterByNickCommand));
                        }
                    }

                    Mails = list;
                }
                else
                {
                    RaiseError(evArgs.ErrorMessage);
                }

                UnSetInDeterminate(GETTINGMAILS_ID);
                Working = false;
            });
        }

        private List<MailModel> _mails;
        public List<MailModel> Mails
        {
            get { return _mails; }
            set
            {
                _mails = value;
                RaisePropertyChanged(() => Mails);
            }
        }

        public override void Enter()
        {
            Refresh();
        }

        public override IEnumerable<AppBarButton> AppBarButtons
        {
            get
            {
                yield return _newMessageButton;
                yield return _searchButton;
                yield return _refreshButton;
            }
        }

        private bool _queryVisible;

        public bool QueryVisible
        {
            get { return _queryVisible || !string.IsNullOrEmpty(FilterByNick) || !string.IsNullOrEmpty(FilterByContent); }
            set
            {
                _queryVisible = value;
                RaisePropertyChanged(() => QueryVisible);
            }
        }

        private string _filterByNick;

        public string FilterByNick
        {
            get { return _filterByNick; }
            set
            {
                _filterByNick = value;
                RaisePropertyChanged(() => FilterByNick);
                RaisePropertyChanged(() => QueryVisible);
            }
        }

        private string _filterByContent;

        public string FilterByContent
        {
            get { return _filterByContent; }
            set
            {
                _filterByContent = value;
                RaisePropertyChanged(() => FilterByContent);
                RaisePropertyChanged(() => QueryVisible);
            }
        }

        private AppBarButton _newMessageButton;

        public void ResetQuery()
        {
            _lastSearchQuery = null;
            FilterByNick = null;
            FilterByContent = null;
            QueryVisible = false;
        }

        public Command FilterCommand
        {
            get;
            private set;
        }

        public Command FilterByNickCommand
        {
            get;
            private set;
        }

        public Command MoreCommand
        {
            get;
            private set;
        }

        public bool Working
        {
            get { return _working; }
            set
            {
                if (_working != value)
                {
                    _working = value;
                    RaisePropertyChanged(() => Working);
                    RaisePropertyChanged(() => NotWorking);
                    FilterCommand.RaiseCanExecuteChanged();
                    FilterByNickCommand.RaiseCanExecuteChanged();
                    MoreCommand.RaiseCanExecuteChanged();
                }
            }
        }

        public bool NotWorking
        {
            get { return !_working; }
            set
            {
                Working = !value;
            }
        }
    }
}
